/*
 * libExtended2.c
 *
 *  Created on: 16/04/2012
 *      Author: utnso
 */

#include "libExtended2.h"

static staticGroupDescriptor_t* staticGroupDescriptorTable = NULL;
static staticSuperBlock_t staticSuperBlock = { 0 };
static pthread_rwlock_t rwlockSuperBlock = PTHREAD_RWLOCK_INITIALIZER;

//LECTURA Y ESCRITURA DE BLOQUES

char* leerBloqueLocal(uint64_t numBlockGroup, uint64_t numBlock) {
	uint32_t blocksPerGroup = staticSuperBlock.blocksPerGroup;
	uint64_t numBloqueGlobal = deBloqueLocalAGlobal(numBlockGroup, blocksPerGroup, numBlock);
	return leerBloqueGlobal(numBloqueGlobal);
}

char* leerBloqueGlobal(uint64_t numBlock) {
	char* contenido;
	uint32_t blockSize = staticSuperBlock.blockSize;
	contenido = leerBytes((off_t) numBlock * blockSize, (size_t) blockSize);
	return contenido;
}

char* leerParteBloqueLocal(uint64_t numBlockGroup, uint64_t numBlock, uint64_t byteInicio, uint64_t byteFin) {
	uint32_t blocksPerGroup = staticSuperBlock.blocksPerGroup;
	uint64_t numBloqueGlobal = deBloqueLocalAGlobal(numBlockGroup, blocksPerGroup, numBlock);
	return leerParteBloqueGlobal(numBloqueGlobal, byteInicio, byteFin);
}

char* leerParteBloqueGlobal(uint64_t numBloque, uint64_t byteInicio, uint64_t byteFin) {
	char* contenidoAux = leerBloqueGlobal(numBloque);
	char* contenido = (char*) malloc(byteFin - byteInicio + 1);
	memcpy(contenidoAux + byteInicio, contenido, byteFin - byteInicio + 1);
	free(contenidoAux);
	return contenido;
}

uint8_t escribirBloqueLocal(uint64_t numBlockGroup, uint64_t numBlock, char* contenido) {
	uint32_t blocksPerGroup = staticSuperBlock.blocksPerGroup;
	uint64_t numBloqueGlobal = deBloqueLocalAGlobal(numBlockGroup, blocksPerGroup, numBlock);
	return escribirBloqueGlobal(numBloqueGlobal, contenido);
}

uint8_t escribirBloqueGlobal(uint64_t numBlock, char* contenido) {
	uint32_t blockSize = staticSuperBlock.blockSize;
	escribirBytes((off_t) numBlock * blockSize, (size_t) blockSize, contenido);
	return 0;
}

uint8_t escribirParteBloqueLocal(uint64_t numBlockGroup, uint64_t numBlock, uint64_t byteInicio, uint64_t byteFin, char* contenido) {
	uint32_t blocksPerGroup = staticSuperBlock.blocksPerGroup;
	uint64_t numBloqueGlobal = deBloqueLocalAGlobal(numBlockGroup, blocksPerGroup, numBlock);
	return escribirParteBloqueGlobal(numBloqueGlobal, byteInicio, byteFin, contenido);
}

uint8_t escribirParteBloqueGlobal(uint64_t numBloque, uint64_t byteInicio, uint64_t byteFin, char* contenido) {
	char* contenidoAux = leerBloqueGlobal(numBloque);
	memcpy(contenidoAux + byteInicio, contenido, byteFin - byteInicio + 1);
	escribirBloqueGlobal(numBloque, contenidoAux);
	free(contenidoAux);
	return 0;
}

uint64_t deBloqueLocalAGlobal(uint64_t numBlockGroup, uint64_t blocksPerGroup, uint64_t numBlock) {
	return ((numBlockGroup * blocksPerGroup) + numBlock);
}

uint64_t deBloqueGlobalALocal(uint64_t blocksPerGroup, uint64_t numBlock) {
	return (div(numBlock, blocksPerGroup).quot);
}

//LECTURA DE ESTRUCTURAS EN EL DISCO

superBlock_t leerSuperBlock(void) {
	pthread_rwlock_rdlock(&rwlockSuperBlock);
	char* contenido = leerBytes(1024, 1024);
	pthread_rwlock_unlock(&rwlockSuperBlock);
	superBlock_t superBloque;
	memcpy(&superBloque, contenido, 1024);
	free(contenido);
	if (staticSuperBlock.inicializado == 0) {
		staticSuperBlock.inodesCount = superBloque.inodesCount;
		staticSuperBlock.blocksCount = superBloque.blocksCount;
		staticSuperBlock.reservedBlocksCount = superBloque.reservedBlocksCount;
		staticSuperBlock.firstDataBlock = superBloque.firstDataBlock;
		staticSuperBlock.blockSize = superBloque.blockSize;
		staticSuperBlock.fragmentSize = superBloque.fragmentSize;
		staticSuperBlock.blocksPerGroup = superBloque.blocksPerGroup;
		staticSuperBlock.fragmentsPerGroup = superBloque.fragmentsPerGroup;
		staticSuperBlock.inodesPerGroup = superBloque.inodesPerGroup;
		staticSuperBlock.firstInode = superBloque.firstInode;
		staticSuperBlock.inodeSize = superBloque.inodeSize;
		staticSuperBlock.superBlockGroup = superBloque.superBlockGroup;
	}
	return superBloque;
}

uint16_t cantBlockGroups(void) {
	//TODO consultar si los grupos de bloques tienen siempre la misma cantidad de bloques
	return staticSuperBlock.blocksCount / staticSuperBlock.blocksPerGroup;
}

uint64_t groupDescriptorTableSize(void) {
	return cantBlockGroups() * sizeof(groupDescriptor_t);
}

uint8_t bloqueInicioGroupDescriptorTable(void) {
	//TODO consultar ¿es el bloque siguiente al superbloque?, ¿o puede comenzar en medio de un bloque?
	//comienza luego del boot record (1024) y el superbloque (1024)
	uint16_t byteInicioGroupDescriptorTable = 1024 + 1024;
	div_t division = div(byteInicioGroupDescriptorTable, staticSuperBlock.blockSize);
	uint8_t bloqueInicio = division.quot;
	if (division.rem != 0) {
		bloqueInicio++;
	}
	bloqueInicio++;
	return bloqueInicio;
}

uint16_t cantBloquesGroupDescriptorTable(void) {
	div_t division = div(groupDescriptorTableSize(), staticSuperBlock.blockSize);
	uint8_t cantBloques = division.quot;
	if (division.rem != 0) {
		cantBloques++;
	}
	return cantBloques;
}

groupDescriptor_t* leerGroupDescriptorTable(void) {
	//leo los bloques correspondientes
	char* contenido = (char*) malloc(groupDescriptorTableSize());
	uint16_t i;
	uint8_t bloqueInicio = bloqueInicioGroupDescriptorTable();
	uint16_t cantBloques = cantBloquesGroupDescriptorTable();
	for (i = 0; i < cantBloques - 1; i++) {
		char* contenidoAux = leerBloqueGlobal(bloqueInicio + i);
		memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, staticSuperBlock.blockSize);
		free(contenidoAux);
	}
	uint16_t resto = div(groupDescriptorTableSize(), staticSuperBlock.blockSize).rem;
	if (resto != 0) {
		char* contenidoAux = leerParteBloqueGlobal(bloqueInicio + i, (bloqueInicio + i) * staticSuperBlock.blockSize, resto);
		memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, resto);
		free(contenidoAux);
	} else {
		char* contenidoAux = leerBloqueGlobal(bloqueInicio + i);
		memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, staticSuperBlock.blockSize);
		free(contenidoAux);
	}
	groupDescriptor_t *groupDescriptor = (groupDescriptor_t*) malloc(groupDescriptorTableSize());
	memcpy(&groupDescriptor, contenido, groupDescriptorTableSize());
	free(contenido);
	if(staticGroupDescriptorTable == NULL){
		cargarStaticGroupDescriptorTable(groupDescriptor);
	}
	return groupDescriptor;
}

void cargarStaticGroupDescriptorTable(groupDescriptor_t* groupDescriptorTable){
	staticGroupDescriptorTable = (staticGroupDescriptor_t*) malloc(cantBlockGroups() * sizeof(staticGroupDescriptor_t));
	uint16_t i;
	for(i = 0; i < cantBlockGroups(); i++){
		staticGroupDescriptorTable[i].blockBitmap = groupDescriptorTable[i].blockBitmap;
		staticGroupDescriptorTable[i].inodeBitmap = groupDescriptorTable[i].inodeBitmap;
		staticGroupDescriptorTable[i].inodeTable = groupDescriptorTable[i].inodeTable;
	}
}

uint64_t blockBitmapSize(void) {
	//TODO revisar
	return staticSuperBlock.blocksPerGroup / 8;
}

uint8_t estaOcupadoBloque(byteBitmap_t* blockBitmap, uint64_t numBloque) {
	div_t division = div(numBloque, 8);
	uint64_t numByte = division.quot;
	uint8_t numBit = division.rem;
	uint8_t retorno;
	switch (numBit) {
	case 0:
		retorno = blockBitmap[numByte].byte0;
		break;
	case 1:
		retorno = blockBitmap[numByte].byte1;
		break;
	case 2:
		retorno = blockBitmap[numByte].byte2;
		break;
	case 3:
		retorno = blockBitmap[numByte].byte3;
		break;
	case 4:
		retorno = blockBitmap[numByte].byte4;
		break;
	case 5:
		retorno = blockBitmap[numByte].byte5;
		break;
	case 6:
		retorno = blockBitmap[numByte].byte6;
		break;
	case 7:
		retorno = blockBitmap[numByte].byte7;
		break;
	}
	return retorno;
}

uint64_t inodeBitmapSize(void) {
	//TODO revisar
	return staticSuperBlock.inodesPerGroup / 8;
}

uint8_t estaOcupadoInodo(byteBitmap_t* inodeBitmap, uint64_t numInodo) {
	div_t division = div(numInodo, 8);
	uint64_t numByte = division.quot;
	uint8_t numBit = division.rem;
	uint8_t retorno;
	switch (numBit) {
	case 0:
		retorno = inodeBitmap[numByte].byte0;
		break;
	case 1:
		retorno = inodeBitmap[numByte].byte1;
		break;
	case 2:
		retorno = inodeBitmap[numByte].byte2;
		break;
	case 3:
		retorno = inodeBitmap[numByte].byte3;
		break;
	case 4:
		retorno = inodeBitmap[numByte].byte4;
		break;
	case 5:
		retorno = inodeBitmap[numByte].byte5;
		break;
	case 6:
		retorno = inodeBitmap[numByte].byte6;
		break;
	case 7:
		retorno = inodeBitmap[numByte].byte7;
		break;
	}
	return retorno;
}

uint64_t inodeTableSize(){
	return staticSuperBlock.inodesPerGroup * sizeof(inodeStructure_t);
}

//TODO HASTA ACA ESTA REVISADO

inodeStructure_t* parsearInodeTable(nodoBloque_t* colaBloquesFte, nodoBloque_t* colaBloquesFin) {
	inodeStructure_t* inodeTable = (inodeStructure_t*) malloc(cantidadNodosBloques(colaBloquesFte, colaBloquesFin) * staticSuperBlock.blockSize);
	nodoBloque_t* aux = colaBloquesFte;
	uint64_t pos = 0;
	while (aux != NULL) {
		memcpy((inodeTable + pos), aux->contenidoBloque, staticSuperBlock.blockSize);
		aux = aux->sig;
		pos = pos + (staticSuperBlock.blockSize / sizeof(inodeStructure_t));
	}
	return inodeTable;
}

/*char* leerParteArchivo(inodeStructure_t inodo, uint64_t numBlockGroup, uint64_t blocksPerGroup, uint64_t byteDesde, uint64_t byteHasta){
 uint64_t primerBloqueArchivoALeer = div(byteDesde, staticSuperBlock.blockSize).quot;
 uint64_t desplazamientoPrimerBloqueArchivo = div(byteDesde, staticSuperBlock.blockSize).rem;
 uint64_t ultimoBloqueArchivoALeer = div(byteHasta, staticSuperBlock.blockSize).quot;
 uint64_t desplazamientoUltimoBloqueArchivo = div(byteHasta, staticSuperBlock.blockSize).rem;
 char* contenido = NULL;//(char*) malloc(byteHasta - byteDesde + 1);

 if(primerBloqueArchivoALeer == ultimoBloqueArchivoALeer){
 if(primerBloqueArchivoALeer < 13){
 //EL INODO DIRECCIONA DIRECTAMENTE AL BLOQUE
 contenido = leerParteBloqueLocal(numBlockGroup, blocksPerGroup, inodo.block[primerBloqueArchivoALeer], desplazamientoPrimerBloqueArchivo, desplazamientoUltimoBloqueArchivo);
 }else if(primerBloqueArchivoALeer >= 13 && primerBloqueArchivoALeer < ((staticSuperBlock.blockSize / 4) + 13)){
 //EL INODO APUNTA A UN BLOQUE CON DIRECCIONES DE BLOQUE
 uint32_t* tablaBloques = obtenerTablaDeBloques(numBlockGroup, blocksPerGroup, inodo.block[13]);
 uint64_t numBloque = primerBloqueArchivoALeer - 13;
 contenido = leerParteBloqueLocal(numBlockGroup, blocksPerGroup, tablaBloques[numBloque], desplazamientoPrimerBloqueArchivo, desplazamientoUltimoBloqueArchivo);
 }else if(primerBloqueArchivoALeer >= ((staticSuperBlock.blockSize / 4) + 13) && primerBloqueArchivoALeer < ((staticSuperBlock.blockSize * staticSuperBlock.blockSize / 4) + (staticSuperBlock.blockSize / 4) + 13)){
 //EL INODO APUNTA A UN BLOQUE CON PUNTEROS A BLOQUES CON DIRECCIONES DE BLOQUE

 }
 }
 if(primerBloqueArchivoALeer < 13){
 //LOS PRIMEROS NUMEROS DE BLOQUE ESTAN EN EL INODO
 uint64_t i;
 for(i = primerBloqueArchivoALeer; i < 13 && i < ultimoBloqueArchivoALeer;)
 }else{
 //TENGO QUE LEER LAS TABLAS CORRESPONDIENTES
 }





 uint64_t cantBloquesCompletos = div(inodo.size, staticSuperBlock.blockSize).quot;
 uint64_t bytesUltimoBloque = div(inodo.size, staticSuperBlock.blockSize).rem;
 memset(contenido, '\0', inodo.size);
 uint64_t i;
 for(i = 0; i < 13 && i < cantBloquesCompletos; i++){
 char* contenidoBloque = leerBloqueLocal(numBlockGroup, blocksPerGroup, inodo.block[i]);
 memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoBloque, staticSuperBlock.blockSize);
 free(contenidoBloque);
 }
 if(i == 13 && cantBloquesCompletos >= 13){
 uint32_t* tablaDeBloques = obtenerTablaDeBloques(numBlockGroup, blocksPerGroup, inodo.block[i]);
 uint64_t cantBloquesEnTabla = staticSuperBlock.blockSize / 4;
 for(; i < cantBloquesEnTabla && i < cantBloquesCompletos; i++){

 }
 }else if(i == 13 && cantBloquesCompletos < 13){

 }else{

 }
 }*/

uint32_t* obtenerTablaDeBloques(uint64_t numBlockGroup, uint64_t numBlock) {
	char* contenidoBloque = leerBloqueLocal(numBlockGroup, numBlock);
	uint32_t* tabla = NULL;
	if (contenidoBloque != NULL) {
		tabla = (uint32_t*) malloc(staticSuperBlock.blockSize);
		memset(tabla, '0', staticSuperBlock.blockSize);
		memcpy(tabla, contenidoBloque, staticSuperBlock.blockSize);
	}
	free(contenidoBloque);
	return tabla;
}

void encolarBloque(nodoBloque_t** colaBloquesFte, nodoBloque_t** colaBloquesFin, char bloque[staticSuperBlock.blockSize]) {
	nodoBloque_t* nue = (nodoBloque_t*) malloc(sizeof(nodoBloque_t));
	memcpy(nue->contenidoBloque, bloque, staticSuperBlock.blockSize);
	nue->sig = NULL;

	if (*colaBloquesFte == NULL) {
		*colaBloquesFte = nue;
	} else {
		(*colaBloquesFin)->sig = nue;
	}
	*colaBloquesFin = nue;
}

char* desencolarBloque(nodoBloque_t** colaBloquesFte, nodoBloque_t** colaBloquesFin) {
	char* contenidoBloque = (char*) malloc(staticSuperBlock.blockSize);
	memcpy(contenidoBloque, (*colaBloquesFte)->contenidoBloque, staticSuperBlock.blockSize);

	nodoBloque_t* aux = malloc(sizeof(nodoBloque_t));
	aux = *colaBloquesFte;
	*colaBloquesFte = (*colaBloquesFte)->sig;
	if (*colaBloquesFte == NULL) {
		*colaBloquesFin = NULL;
	}
	free(aux);
	return contenidoBloque;
}

uint64_t cantidadNodosBloques(nodoBloque_t* colaBloquesFte, nodoBloque_t* colaBloquesFin) {
	uint64_t i;
	nodoBloque_t* aux;
	for (i = 0, aux = colaBloquesFte; aux != NULL; aux = aux->sig, i++)
		;
	return i;
}

uint8_t buscarEnDirBloque(char* bloque, uint64_t cantBytes, char* nombre, inodeStructure_t* inodoBuscado) {
	uint8_t encontrado = 0;
	uint64_t i;
	for (i = 0; i < cantBytes && !encontrado;) {
		uint64_t iAux = i;
		if ((iAux + 4) < cantBytes) {
			uint32_t numInodo;
			memcpy(&numInodo, bloque + i, 4);
			iAux += 4;
			if ((iAux + 2) < cantBytes) {
				uint16_t longRegistro;
				memcpy(&longRegistro, bloque + iAux, 2);
				iAux += 2;
				if ((iAux + 1) < cantBytes) {
					uint8_t longNombre;
					memcpy(&longNombre, bloque + iAux, 1);
					iAux += 1;
					if ((iAux + longNombre) < cantBytes) {
						char* nombreAux = malloc(longNombre + 1);
						memset(nombreAux, '\0', longNombre + 1);
						memcpy(nombreAux, bloque + iAux, longNombre);
						iAux += longNombre;
						if (strcmp(nombreAux, nombre) == 0) {
							encontrado = 1;
							//TODO
							/*buscar el inodo y cargarlo en inodoBuscado*/
							div_t division = div(longRegistro, 4);
							i += division.quot + division.rem;
						}

					}
				}
			}
		}
	}
	return encontrado;
}

uint8_t buscarEnDirNivel0(uint32_t* bloques, uint64_t cantPunteros, char* nombre, inodeStructure_t* inodoBuscado) {
	uint8_t encontrado = 0;
	uint32_t i;
	for (i = 0; i < cantPunteros && !encontrado; i++) {
		char* buffer = leerBloqueGlobal(bloques[i]);
		pthread_rwlock_rdlock(&rwlockSuperBlock);
		uint32_t tamanioBloque = staticSuperBlock.blockSize;
		pthread_rwlock_unlock(&rwlockSuperBlock);
		char* bloquesAux = (char*) malloc(tamanioBloque);
		memset(bloquesAux, 0, tamanioBloque);
		memcpy(bloquesAux, buffer, tamanioBloque);
		encontrado = buscarEnDirBloque(bloquesAux, tamanioBloque, nombre, inodoBuscado);
		free(bloquesAux);
	}
	return encontrado;
}

uint8_t buscarEnDirNivel1(uint32_t* bloques, uint64_t cantPunteros, char* nombre, inodeStructure_t* inodoBuscado) {
	uint8_t encontrado = 0;
	uint32_t i;
	for (i = 0; i < cantPunteros && !encontrado; i++) {
		char* buffer = leerBloqueGlobal(bloques[i]);
		pthread_rwlock_rdlock(&rwlockSuperBlock);
		uint32_t tamanioBloque = staticSuperBlock.blockSize;
		pthread_rwlock_unlock(&rwlockSuperBlock);
		uint32_t* bloquesAux = (uint32_t*) malloc(tamanioBloque);
		memset(bloquesAux, 0, tamanioBloque);
		memcpy(bloquesAux, buffer, tamanioBloque);
		encontrado = buscarEnDirNivel0(bloquesAux, tamanioBloque / sizeof(uint32_t), nombre, inodoBuscado);
		free(bloquesAux);
	}
	return encontrado;
}

uint8_t buscarEnDirNivel2(uint32_t* bloques, uint64_t cantPunteros, char* nombre, inodeStructure_t* inodoBuscado) {
	uint8_t encontrado = 0;
	uint32_t i;
	for (i = 0; i < cantPunteros && !encontrado; i++) {
		char* buffer = leerBloqueGlobal(bloques[i]);
		pthread_rwlock_rdlock(&rwlockSuperBlock);
		uint32_t tamanioBloque = staticSuperBlock.blockSize;
		pthread_rwlock_unlock(&rwlockSuperBlock);
		uint32_t* bloquesAux = (uint32_t*) malloc(tamanioBloque);
		memset(bloquesAux, 0, tamanioBloque);
		memcpy(bloquesAux, buffer, tamanioBloque);
		encontrado = buscarEnDirNivel1(bloquesAux, tamanioBloque / sizeof(uint32_t), nombre, inodoBuscado);
		free(bloquesAux);
	}
	return encontrado;
}

uint8_t buscarEnDirNivel3(uint32_t* bloques, uint64_t cantPunteros, char* nombre, inodeStructure_t* inodoBuscado) {
	uint8_t encontrado = 0;
	uint32_t i;
	for (i = 0; i < cantPunteros && !encontrado; i++) {
		char* buffer = leerBloqueGlobal(bloques[i]);
		pthread_rwlock_rdlock(&rwlockSuperBlock);
		uint32_t tamanioBloque = staticSuperBlock.blockSize;
		pthread_rwlock_unlock(&rwlockSuperBlock);
		uint32_t* bloquesAux = (uint32_t*) malloc(tamanioBloque);
		memset(bloquesAux, 0, tamanioBloque);
		memcpy(bloquesAux, buffer, tamanioBloque);
		encontrado = buscarEnDirNivel2(bloquesAux, tamanioBloque / sizeof(uint32_t), nombre, inodoBuscado);
		free(bloquesAux);
	}
	return encontrado;
}

uint8_t buscarEnDir(inodeStructure_t inodoDir, char* nombre, inodeStructure_t* inodoBuscado) {
	uint8_t encontrado = 0;
	uint32_t* bloques = (uint32_t*) malloc(12);
	memcpy(bloques, inodoDir.block, 12 * sizeof(uint32_t));
	encontrado = buscarEnDirNivel0(bloques, 12, nombre, inodoBuscado);
	free(bloques);
	if (!encontrado) {
		bloques = (uint32_t*) malloc(sizeof(uint32_t));
		memcpy(bloques, inodoDir.block + 12, sizeof(uint32_t));
		encontrado = buscarEnDirNivel1(bloques, 1, nombre, inodoBuscado);
		free(bloques);
		if (!encontrado) {
			bloques = (uint32_t*) malloc(sizeof(uint32_t));
			memcpy(bloques, inodoDir.block + 13, sizeof(uint32_t));
			encontrado = buscarEnDirNivel2(bloques, 1, nombre, inodoBuscado);
			free(bloques);
			if (!encontrado) {
				bloques = (uint32_t*) malloc(sizeof(uint32_t));
				memcpy(bloques, inodoDir.block + 14, sizeof(uint32_t));
				encontrado = buscarEnDirNivel3(bloques, 1, nombre, inodoBuscado);
				free(bloques);
			}
		}
	}
	return encontrado;
}

inodeStructure_t inodoDirectorioRaiz() {
	//TODO
	inodeStructure_t inodo;
	return inodo;
}

uint8_t obtenerInodoPath(char* path, inodeStructure_t* inodoBuscado) {
	nodoNombreDirOArch_t* listaPath = parsearPath(path);

	inodeStructure_t inodoAux = inodoDirectorioRaiz();
	uint8_t error = 0;
	while (!error && listaPath != NULL) {
		char* nombre;
		desapilarNombreDirOArch(&listaPath, &nombre);
		error = buscarEnDir(inodoAux, nombre, &inodoAux);
		free(nombre);
	}
	if (!error) {
		*inodoBuscado = inodoAux;
	}
	return error;
}

int32_t crearArchivo(char* path, mode_t modo) {
	return 0;
}

int32_t leerDirectorio(char* path, off_t offset) {
	inodeStructure_t inodoDir;
	uint8_t error = obtenerInodoPath(path, &inodoDir);
	if (!error) {
		//TODO
		return 0;
	} else {
		return -ENOENT;
	}
}

int32_t obtenerAtributos(char* path, attrDirArch_t *attr) {
	inodeStructure_t inodo;
	uint8_t error = obtenerInodoPath(path, &inodo);
	if (!error) {
		attr->modo = inodo.mode;
		attr->size = inodo.size;
		return 0;
	} else {
		return -ENOENT;
	}
}

char* leerGrupoDeBloques(uint64_t numGroup, uint32_t blockPerGroup, uint32_t blockSize, FILE* particion) {
	char* contenido = malloc(blockPerGroup * blockSize);
	fseek(particion, 1024 + (numGroup * blockPerGroup * blockSize), SEEK_SET);
	memcpy(&contenido, particion, blockPerGroup * blockSize);
	return contenido;
}

uint16_t grupoConSuperBloque(uint64_t numeroDeGrupo) {
	if ((numeroDeGrupo == 0) || (numeroDeGrupo == 1) || (esPotencia(numeroDeGrupo, 3)) || esPotencia(numeroDeGrupo, 5) || esPotencia(numeroDeGrupo, 7))
		return 1;
	else
		return 0;
}

int64_t buscarBloqueLibre(byteBitmap_t * blockBitmap, uint32_t blocksPerGroup) {
	uint64_t encontrado = -1, i;
	for (i = 0; (i < blocksPerGroup) && (encontrado == -1); i++) {
		if (!(estaOcupadoBloque(blockBitmap, i)))
			encontrado = i;
	}
	return encontrado;
}

int64_t buscarInodoLibre(byteBitmap_t *inodeBitmap, uint32_t inodesPerGroup) {
	uint64_t encontrado = -1, i;
	for (i = 0; (i < inodesPerGroup) && (encontrado == -1); i++) {
		if (!(estaOcupadoInodo(inodeBitmap, i)))
			encontrado = i;
	}
	return encontrado;
}

void finalizarExtended2(void){
	if(staticGroupDescriptorTable != NULL){
		free(staticGroupDescriptorTable);
		staticGroupDescriptorTable = NULL;
	}
}
